package it.polito.connectedcar.trafficlight.network;

import it.polito.connectedcar.general.network.ConnectedCarSocket;
import it.polito.connectedcar.general.network.EntityNetworkConnectorFactory;
import it.polito.connectedcar.message.TrafficLightToTCCMessage;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.SocketException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * This network manager is used by a Traffic Light to pack messages into
 * datagrams to be sent to TCC periodically( normally this data are sent
 * whenever the Traffic Light phase changes It uses a worker thread which
 * sequentially extracts messages from a queues ( properly filled by upper
 * layers) and send them to the TCC by using the opened socket
 * 
 * @author Nicola Aresta
 * 
 */
public class TrafficLightNetworkConnectionManager {

	private BlockingQueue<TrafficLightToTCCMessage> toBeSentMessagesQueue;
	private Thread socketWriterThread;
	private ConnectedCarSocket socket;

	public TrafficLightNetworkConnectionManager() {
		try {
			init();
		} catch (SocketException e) {
			e.printStackTrace();
		}
	}

	public void init() throws SocketException {

		setToBeSentMessagesQueue(new LinkedBlockingQueue<TrafficLightToTCCMessage>());
		socket = EntityNetworkConnectorFactory.newFactoryInstance().getSocket();
		socketWriterThread = new Thread(new SocketWriter(socket));
		socketWriterThread.start();
	}

	public BlockingQueue<TrafficLightToTCCMessage> getToBeSentMessagesQueue() {
		return toBeSentMessagesQueue;
	}

	public void setToBeSentMessagesQueue(
			BlockingQueue<TrafficLightToTCCMessage> toBeSentMessagesQueue) {
		this.toBeSentMessagesQueue = toBeSentMessagesQueue;
	}

	private class SocketWriter implements Runnable {

		private ConnectedCarSocket dsocket;

		public SocketWriter(ConnectedCarSocket dsocket) {
			this();
			this.dsocket = dsocket;
		}

		private SocketWriter() {
		}

		@Override
		public void run() {

			while (!dsocket.isClosed()) {
				try {
					TrafficLightToTCCMessage m = toBeSentMessagesQueue.take();
					byte[] packetData = m.getMessageAsBytes(false, null);
					DatagramPacket dp = new DatagramPacket(packetData,packetData.length, m.getTccAddress());
					dsocket.send(dp);
					// FIXME
				} catch (InterruptedException e) {
					e.printStackTrace();
					break;
				} catch (SocketException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}
